home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 401-425 / disk_405 / gifmachine / sources / main.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  12KB  |  504 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6. #include <dos/rdargs.h>
  7. #include <dos/dosasl.h>
  8. #include <dos/stdio.h>
  9. #include <workbench/startup.h>
  10.  
  11. struct GIFdescriptor gdesc;
  12.  
  13. struct RGB **BitPlane;
  14. struct RGB GlobalColourTable[256];
  15.  
  16. extern UWORD *SHAMmem;
  17.  
  18. extern BYTE *PlaneBuf;
  19.  
  20. extern BOOL Laced;
  21.  
  22. extern UBYTE *Planes[8];
  23.  
  24. ULONG ImageNumber;
  25.  
  26. extern struct MinList CommentList;
  27.  
  28. /* our version number stuff */
  29. extern UBYTE __far VersionID[];
  30.  
  31. /* indicates which memory list to allocate from */
  32. extern UWORD CurrentMem;
  33.  
  34. /* the current GIF file handle */
  35. BPTR GIFfh = NULL;
  36.  
  37. /* here we have some defines relating to our GADS call */
  38. #define ESC "\x9B"
  39. #define GIFMACH ESC "33;42mGIFMachine" ESC "32;40m"
  40. #define SPACES    ESC "32m]\n                      [" ESC "33m"
  41. #define BRACES    ESC "32m] [" ESC "33m"
  42. #define ARG_HELP    "%s v%s\nCopyright \xA9 1990 by " \
  43.         ESC "4;33;42mChristopher A. Wichura" ESC "0;33;40m (" \
  44.         ESC "32mcaw" ESC "33m@" ESC "32mmiroc.chi.il.us" ESC "33m)\n\n" \
  45.         ESC "31mUsage:     %s <" ESC "31mGIFfile(s)" ESC "32m> [" \
  46.         ESC "33mTO " ESC "31mDirectory | File" BRACES "ALL%s" \
  47.         "NOBORDER " ESC "32m<" ESC "31mLine Thresh" ESC "32m>] [" ESC \
  48.         "33mXCOMP" BRACES "DITHER%sXFLIP" BRACES "YFLIP" BRACES \
  49.         "DEEP" BRACES "BUFSIZE " ESC "32m<" ESC "31mSize in Kbytes" \
  50.         ESC "32m>]\n" ESC "31m"
  51.  
  52. #define ARG_TEMPLATE "GIFfiles/M/A,TO/K,ALL/S,NOBORDER/K/N,XCOMP/S,DITHER/S,XFLIP/s,YFLIP/s,DEEP/S,BUFSIZE/K/N"
  53. #define ARG_FILES  0
  54. #define ARG_TO     1
  55. #define ARG_ALL    2
  56. #define ARG_NOBORD 3
  57. #define ARG_XCOMP  4
  58. #define ARG_DITHER 5
  59. #define ARG_FLIPX  6
  60. #define ARG_FLIPY  7
  61. #define ARG_DEEP   8
  62. #define ARG_BUFSIZ 9
  63. #define ARG_sizeof 10
  64.  
  65. /* we will make the argument array global so that other modules can get at
  66.    the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
  67. struct RDArgs *ArgsPtr;
  68. char *ArgArray[ARG_sizeof];
  69. BOOL ArgToIsDir;
  70.  
  71. /* size of the read buffered i/o space */
  72. static ULONG BufSize = 2048;    /* default size is 2k */
  73.  
  74. int NoBorderLineThresh = 0;
  75.  
  76. /* some mem pointers used when we do dithering */
  77. BYTE *CurrentLineErr[3];
  78. BYTE *LastLineErr[3];
  79.  
  80. /* this flag says if we scaled the image */
  81. BOOL DidXComp;
  82.  
  83. /* we print this when the user hits the break key */
  84. char *AbortMsg = "*** User Interruption!\n";
  85.  
  86. /* storage for our library bases */
  87. struct Library *MathIeeeDoubBasBase = NULL;
  88. struct Library *IFFParseBase = NULL;
  89.  
  90. /* storage for our anchor when looking for pattern matches */
  91. struct Anchor {
  92.         struct AnchorPath APath;
  93.         char              Path[256];
  94.     } *anchor = NULL;
  95.  
  96. /* here we have our main routine */
  97. int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
  98. {
  99.     register char **FilesPtr;
  100.     struct RDArgs MyArgs;
  101.  
  102.     InitMemory();
  103.  
  104.     if (WBMsg) {
  105.         WarnMustUseCLI();
  106.         MyExit(5);
  107.     }
  108.  
  109.     if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
  110.         MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
  111.         MyExit(5);
  112.     }
  113.  
  114.     if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
  115.         MyPrintf("Unable to access %s!\n", "iffparse.library");
  116.         MyExit(5);
  117.     }
  118.  
  119.     memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
  120.  
  121.     if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(ARG_HELP) + (2 * strlen(GIFMACH)) + (2 * strlen(SPACES)) + strlen(VersionID) + 1))) {
  122.         PutStr("Out of memory!\n");
  123.         MyExit(5);
  124.     }
  125.  
  126.     MySPrintf((char *)MyArgs.RDA_ExtHelp, ARG_HELP, GIFMACH, VersionID, GIFMACH, SPACES, SPACES);
  127.  
  128.     if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
  129.         PrintFault(IoErr(), NULL);
  130.         MyExit(5);
  131.     }
  132.  
  133.     MyFree((char *)MyArgs.RDA_ExtHelp);
  134.  
  135.     if (ArgArray[ARG_TO])
  136.         ArgToIsDir = IsDir(ArgArray[ARG_TO]);
  137.  
  138.     if (ArgArray[ARG_NOBORD]) {
  139.         NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
  140.         if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
  141.             PutStr("Invalid NOBORDER line threshhold specified.\n");
  142.             MyExit(3);
  143.         }
  144.     }
  145.  
  146.     if (ArgArray[ARG_BUFSIZ])
  147.         BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
  148.  
  149.     if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
  150.         PutStr("No GIF files selected.\n");
  151.         MyExit(3);
  152.     }
  153.  
  154.     InitDiff();    /* one time init for the RGBdiff function */
  155.  
  156.     while (*FilesPtr)
  157.         DoPattern(*FilesPtr++);
  158.  
  159.     MyExit(0);
  160. }
  161.  
  162. void MyExit(ULONG result)
  163. {
  164.     if (GIFfh)
  165.         Close(GIFfh);
  166.  
  167.     if (IFFParseBase)
  168.         CloseLibrary(IFFParseBase);
  169.  
  170.     if (MathIeeeDoubBasBase)
  171.         CloseLibrary(MathIeeeDoubBasBase);
  172.  
  173.     if (anchor)
  174.         MatchEnd(&anchor->APath);
  175.  
  176.     if (ArgsPtr)
  177.         FreeArgs(ArgsPtr);
  178.  
  179.     FreeAll(1);
  180.     FreeAll(0);
  181.  
  182.     XCEXIT(result);
  183. }
  184.  
  185.  
  186. /* this will walk through a pattern doing conversions */
  187. void DoPattern(char *pat)
  188. {
  189.     register int error;
  190.  
  191.     if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
  192.         PutStr("Out of memory!\n");
  193.         MyExit(10);
  194.     }
  195.  
  196.     anchor->APath.ap_Strlen = sizeof(anchor->Path);
  197.     anchor->APath.ap_Flags = APF_DOWILD;
  198.     anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
  199.  
  200.     error = MatchFirst(pat, &anchor->APath);
  201.  
  202.     while (!error) {
  203.         if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
  204.             if (ArgArray[ARG_ALL]) {
  205.                 if (!(anchor->APath.ap_Flags & APF_DIDDIR))
  206.                     anchor->APath.ap_Flags |= APF_DODIR;
  207.                 anchor->APath.ap_Flags &= ~APF_DIDDIR;
  208.             }
  209.         } else
  210.             Convert(anchor->APath.ap_Buf);
  211.  
  212.         error = MatchNext(&anchor->APath);
  213.     }
  214.  
  215.     MatchEnd(&anchor->APath);
  216.     MyFree((char *)anchor);
  217.     anchor = NULL;
  218.  
  219.     switch(error) {
  220.         case ERROR_BREAK:
  221.             PutStr(AbortMsg);
  222.             MyExit(ABORTEXITVAL);
  223.             break;
  224.  
  225.         case ERROR_OBJECT_NOT_FOUND:
  226.             PutStr("File not found.\n");
  227.             break;
  228.  
  229.         case ERROR_BUFFER_OVERFLOW:
  230.             PutStr("Path too long!\n");
  231.             break;
  232.  
  233.         case ERROR_NO_MORE_ENTRIES:    /* normal termination */
  234.             break;
  235.  
  236.         default:
  237.             MyPrintf("I/O Error #%ld!\n", error);
  238.             break;
  239.     }
  240. }
  241.  
  242. /* here we have the routine that gets ready to do the conversion */
  243. void Convert(char *name)
  244. {
  245.     register int index;
  246.     char *basename;
  247.     char *ptr;
  248.     char sig[7];
  249.     int size;
  250.     int error;
  251.     int colours;
  252.     LONG cmdcode;
  253.     
  254.     struct DateStamp StartTime, EndTime;
  255.  
  256.     CurrentMem++;
  257.  
  258.     if (!(GIFfh = Open(name, MODE_OLDFILE))) {
  259.         MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
  260.         goto LeaveConvert;
  261.     }
  262.  
  263.     SetVBuf(GIFfh, BUF_FULL, BufSize);
  264.  
  265.     sig[6] = NULL;
  266.  
  267.     if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
  268.         MyPrintf("%s is not a GIF file...\n", name);
  269.         goto LeaveConvert;
  270.     }
  271.  
  272.     MyPrintf("Converting %s ", name);
  273.  
  274.     basename = FilePart(name);
  275.     ptr = basename + strlen(basename) - 4;
  276.  
  277.     if (!strnicmp(".gif", ptr, 4))
  278.         *ptr = NULL;
  279.  
  280.     size = strlen(basename) + 6;
  281.  
  282.     if (ArgArray[ARG_TO]) {
  283.         if (ArgToIsDir)
  284.             size += strlen(ArgArray[ARG_TO]) + 1;
  285.         else
  286.             size = strlen(ArgArray[ARG_TO]) + 1;
  287.     }
  288.  
  289.     if (!(ptr = MyAlloc(size))) {
  290.         PutStr("... Out of memory!\n");
  291.         goto LeaveConvert;
  292.     }
  293.  
  294.     if (ArgArray[ARG_TO]) {
  295.         strcpy(ptr, ArgArray[ARG_TO]);
  296.  
  297.         if (ArgToIsDir) {
  298.             AddPart(ptr, basename, size);
  299.             strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  300.         }
  301.     } else {
  302.         strcpy(ptr, basename);
  303.         strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  304.     }
  305.  
  306.     MyPrintf("to %s...\n", ptr);
  307.  
  308.     DateStamp((LONG *)&StartTime);
  309.  
  310.     if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
  311.         PutStr("Error reading screen descriptor.\n");
  312.         goto LeaveConvert;
  313.     }
  314.  
  315.     FlipWord(&gdesc.gd_Width);
  316.     FlipWord(&gdesc.gd_Height);
  317.  
  318.     MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
  319.         sig, gdesc.gd_Width, gdesc.gd_Height);
  320.  
  321.     NewList((struct List *)&CommentList);
  322.  
  323.     DidXComp = 0;
  324.     colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  325.  
  326.     if (!(gdesc.gd_ColInfo & 1L << 7)) {
  327.         PutStr("No global colour map supplied, using internal.\n");
  328.  
  329.         for (index = 0; index < colours; index++) {
  330.             GlobalColourTable[index].rgb_Red   =
  331.             GlobalColourTable[index].rgb_Green =
  332.             GlobalColourTable[index].rgb_Blue  = index;
  333.         }
  334.     } else {
  335.         MyPrintf("Global colour map contains %ld entries.\n", colours);
  336.  
  337.         for (index = 0; index < colours; index++) {
  338.             if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
  339.                 MyPrintf("Error reading global colour #%ld.\n",
  340.                     index);
  341.                 goto LeaveConvert;
  342.             }
  343.         }
  344.     }
  345.  
  346.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  347.     size += (size + 127) >> 7;
  348.  
  349.     if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
  350.         !(SHAMmem  = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
  351.         !(PlaneBuf = (BYTE *)MyAlloc(size))) {
  352.         PutStr("Out of memory trying to allocate picture.\n");
  353.         goto LeaveConvert;
  354.     }
  355.  
  356.     size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
  357.  
  358.     for (index = 0; index < gdesc.gd_Height; index++)
  359.         if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
  360.             PutStr("Out of memory trying to allocate picture.\n");
  361.             goto LeaveConvert;
  362.         }
  363.  
  364.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  365.     for (index = 0; index < (ArgArray[ARG_DEEP] ? 8 : 6); index++)
  366.         if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
  367.             PutStr("Out of memory trying to allocate picture.\n");
  368.             goto LeaveConvert;
  369.         }
  370.  
  371.     if (ArgArray[ARG_DITHER]) {
  372.         size = gdesc.gd_Width * sizeof(BYTE);
  373.  
  374.         for (index = 0; index < 3; index++)
  375.             if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
  376.                 !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
  377.                 PutStr("Out of memory trying to allocate picture.\n");
  378.                 goto LeaveConvert;
  379.             }
  380.     }
  381.  
  382.     ImageNumber = 1;
  383.  
  384.     /* at this point we start looking for images, extensions or the gif
  385.        terminator.  we call the appropriate routine as we find each. */
  386.  
  387.     for (error = FALSE; error == FALSE;) {
  388.         if ((cmdcode = FGetC(GIFfh)) == -1) {
  389.             PutStr("...I/O error reading GIF file.\n");
  390.             goto LeaveConvert;
  391.         }
  392.  
  393.         switch(cmdcode) {
  394.             case GIF_IMAGE:
  395.                 error = DoImage(GIFfh);
  396.                 break;
  397.  
  398.             case GIF_EXTENSION:
  399.                 error = DoExtension(GIFfh);
  400.                 break;
  401.  
  402.             case GIF_TERMINATOR:
  403.                 if (ArgArray[ARG_NOBORD])
  404.                     StripBorder();
  405.  
  406.                 if (ArgArray[ARG_FLIPX])
  407.                     DoXFlip();
  408.  
  409.                 if (ArgArray[ARG_FLIPY])
  410.                     DoYFlip();
  411.  
  412.                 if (ArgArray[ARG_XCOMP]) {
  413.                     DoXComp();
  414.                     DidXComp = 1;
  415.                 }
  416.  
  417.                 if (gdesc.gd_Height > 200 && DidXComp)
  418.                     Laced = TRUE;
  419.                 else
  420.                     Laced = FALSE;
  421.  
  422.                 if (!ArgArray[ARG_DEEP]) {
  423.                     if (ArgArray[ARG_DITHER])
  424.                         DitherTo12();
  425.                     else
  426.                         ReduceTo12();
  427.  
  428.                     GIFtoSHAM();
  429.                 }
  430.  
  431.                 error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
  432.                 break;
  433.  
  434.             default:
  435.                 MyPrintf("...Unknown directive #%ld encountered.\n",
  436.                     cmdcode);
  437.                 error = TRUE;
  438.         }
  439.     }
  440.  
  441.     DateStamp((ULONG *)&EndTime);
  442.  
  443.     {
  444.         register ULONG Hours;
  445.         register ULONG Minutes;
  446.         register ULONG Seconds;
  447.         register ULONG Seconds2;
  448.     
  449.         Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
  450.         Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
  451.  
  452.         Seconds -= Seconds2;
  453.  
  454.         Hours = Seconds / 3600;
  455.         Seconds -= Hours * 3600;
  456.  
  457.         Minutes = Seconds / 60;
  458.         Seconds -= Minutes * 60;
  459.  
  460.         MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
  461.             Hours, (Hours != 1 ? "s" : ""),
  462.             Minutes, (Minutes != 1 ? "s" : ""),
  463.             Seconds, (Seconds != 1 ? "s" : ""));
  464.     }
  465.  
  466. LeaveConvert:
  467.     FreeAll(CurrentMem--);
  468.  
  469.     if (GIFfh) {
  470.         Close(GIFfh);
  471.         GIFfh = NULL;
  472.     }
  473. }
  474.  
  475. /* this will check to see if we have a directory or not */
  476. BOOL IsDir(char *name)
  477. {
  478.     register BPTR lock;
  479.     register BOOL result = FALSE;
  480.  
  481.     struct FileInfoBlock __aligned fib;
  482.  
  483.     if (lock = Lock(name, ACCESS_READ)) {
  484.         if (Examine(lock, &fib)) {
  485.             if (fib.fib_DirEntryType > 0)
  486.                 result = TRUE;
  487.         }
  488.         UnLock(lock);
  489.     }
  490.  
  491.     return result;
  492. }
  493.  
  494. /* this will convert a word from LSB/MSB to MSB/LSB */
  495. void FlipWord(UWORD *word)
  496. {
  497.     register UBYTE swap1;
  498.     register UBYTE swap2;
  499.  
  500.     swap1 = *word & 0xFF;
  501.     swap2 = (*word & 0xFF00) >> 8;
  502.     *word = swap1 << 8 | swap2;
  503. }
  504.